﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ivony.Fluent
{

  /// <summary>
  /// 提供一系列转换对象类型和值的扩展方法提高编程体验
  /// </summary>
  public static class ConvertExtensions
  {

    /// <summary>
    /// 将对象强制转换为T类型，等同于 ((T) obj)
    /// </summary>
    /// <typeparam name="T">要强制转换的类型</typeparam>
    /// <param name="obj">要被类型转换的对象</param>
    /// <returns>转换后的结果</returns>
    public static T CastTo<T>( this object obj )
    {
      return (T) obj;
    }

    /// <summary>
    /// 将值尝试用Convert的ToXXX方法转换为指定类型，若不能则进行强制类型转换
    /// </summary>
    /// <typeparam name="T">要转换的目标类型</typeparam>
    /// <param name="value">要被类型转换的值</param>
    /// <returns>转换后的值</returns>
    public static T ConvertTo<T>( this object value )
    {
      if ( Convertor<T>.castMethod != null )
        return Convertor<T>.castMethod( value );


      return (T) value;
    }

    static ConvertExtensions()
    {
      Convertor<short>.castMethod    = Convert.ToInt16;
      Convertor<int>.castMethod      = Convert.ToInt32;
      Convertor<long>.castMethod     = Convert.ToInt64;
      Convertor<byte>.castMethod     = Convert.ToByte;
      Convertor<ushort>.castMethod   = Convert.ToUInt16;
      Convertor<uint>.castMethod     = Convert.ToUInt32;
      Convertor<ulong>.castMethod    = Convert.ToUInt64;
      Convertor<sbyte>.castMethod    = Convert.ToSByte;
      Convertor<float>.castMethod    = Convert.ToSingle;
      Convertor<double>.castMethod   = Convert.ToDouble;
      Convertor<decimal>.castMethod  = Convert.ToDecimal;
      Convertor<bool>.castMethod     = Convert.ToBoolean;
      Convertor<DateTime>.castMethod = Convert.ToDateTime;
      Convertor<string>.castMethod   = Convert.ToString;
    }

    private class Convertor<T>
    {
      public static Func<object, T> castMethod;
    }


    /// <summary>
    /// 如果值是null或DbNull，则使用指定默认值，类似于( obj ?? defaultValue )
    /// </summary>
    /// <typeparam name="T">值的类型</typeparam>
    /// <param name="value">要被判断的值</param>
    /// <param name="defaultValue">值为空时应当使用的默认值</param>
    /// <returns>如果值不为空，返回值，否则返回默认值</returns>
    public static T IfNull<T>( this T value, T defaultValue )
    {
      if ( value == null || Convert.IsDBNull( value ) )
        return defaultValue;
      else
        return value;
    }


  }
}
